---
title: "Migrating to the Theming API"
---

Migrating to the Theming API

Before v33, themes were imported as CSS files in our NPM modules, and applied by setting a class name on the grid's container element, e.g. `class="ag-theme-quartz"`. In v33, the default method of styling the grid is the Theming API, in which themes are imported as JavaScript objects and passed to the grid as a grid option. The old method of styling (now called legacy themes) is still supported, but is deprecated and will be removed in a future major version.

To understand the technical context of this change, see [Understanding the Theming API](#understanding-the-theming-api) below.

## Updating your app for v33

In v33, the `theme` grid option has a default value, and if no value is provided the quartz theme will be used.

### Continue with legacy themes

If you want to upgrade to v33 without immediately adopting the Theming API, you can opt back in to the v32 style of themes by passing the string `"legacy"` to the `theme` grid option. You can then continue to use legacy themes.

If you have multiple grids you may find using a [Global Grid Option](./grid-interface/#global-grid-options) to be a convenient way to set the theme to `"legacy"` for all grids in your application.

```ts
import { provideGlobalGridOptions } from 'ag-grid-community';

// Mark all grids as using legacy themes
provideGlobalGridOptions({
    theme: "legacy",
});
```

### Adopt the Theming API

To adopt the v33 themes, follow these steps:

### 1. Remove CSS imports

Applications import the legacy CSS files either through JS (`import 'ag-grid-community/styles/ag-grid.css';`) or by copying the CSS files from the NPM package to the application. Any such CSS imports should be removed.

### 2. Import and use your theme

Themes can be imported from `ag-grid-community` and passed to the `theme` grid option:

```js
import { themeBalham } from 'ag-grid-community';
```

Once imported, you can optionally add default values for any custom properties you want to set using the TypeScript API:

```js
const myTheme = themeBalham.withParams({ accentColor: 'red' });
```

You can then pass your theme to the `theme` grid option:

{% if isFramework("javascript") %}
```js
const gridOptions = {
    theme: myTheme,
    ...
}
```
{% /if %}
{% if isFramework("react") %}
```js
<AgGridReact
    theme={myTheme}
    ...
/>
```
{% /if %}
{% if isFramework("vue") %}
```js
// in template
<ag-grid-vue
    :theme="theme"
    ...
></ag-grid-vue>

// in component setup hook
setup() {
    return {
        theme: myTheme,
    };
}
```
{% /if %}
{% if isFramework("angular") %}
```js
// in template
<ag-grid-angular
    [theme]="theme"
/>

// in component class
public theme = myTheme;
```
{% /if %}

### 3. Convert any css custom properties you are using to the new names

In legacy themes, custom properties had to be set in CSS. When migrating custom properties to the Theming API you may choose whether to specify them in JavaScript in order to get Typescript validation of property names and values, or to continue to set them in CSS. The list below provides the JS API names, to convert them to CSS use kebab-case and add the `--ag-` prefix (`tooltipTextColor` -> `--ag-tooltip-text-color`).

#### Key changes

 * `--ag-grid-size` -> `spacing` spacing works a little bit differently from the old "grid size". It controls the padding around elements, whereas grid size controlled their size. So setting spacing to `0` will result in a grid with no padding, whereas setting grid size to `0` would have resulted in zero-height rows.
 * `--ag-active-color`, `--ag-alpine-active-color`, `--ag-balham-active-color`, `--ag-material-accent-color` -> use `accentColor`
 * `--ag-borders*` -> there has been a reworking of border parameters, see [Customising Borders](./theming-borders/) for the new list of border parameters.
 * `--ag-row-border-color`, `--ag-row-border-style`, `--ag-row-border-width` -> replaced with `rowBorder`
 * `--ag-icon-font-*` and `--ag-icon-image-*` -> use [the iconOverrides part](./custom-icons/#replacing-individual-icons) or use [CSS rules](./custom-icons/#styling-icons-using-css).

#### Properties with a direct replacement

While developing the Theming API we took the opportunity to rename many of our parameters to use a consistent naming scheme and semantics.

Note: the replacement parameter is given as name for use in the TypeScript Theming API, e.g. `chromeBackgroundColor`. To use this in CSS, convert it to kebab-case and add the `--ag-` prefix, e.g. `--ag-chrome-background-color`.

 * `--ag-secondary-foreground-color` -> `chromeBackgroundColor`
 * `--ag-selected-tab-underline-color` -> `tabSelectedUnderlineColor`
 * `--ag-selected-tab-underline-transition-speed` -> `tabSelectedUnderlineTransitionDuration`
 * `--ag-selected-tab-underline-width` -> `tabSelectedUnderlineWidth`
 * `--ag-advanced-filter-column-pill-color` -> `advancedFilterBuilderColumnPillColor`
 * `--ag-advanced-filter-join-pill-color` -> `advancedFilterBuilderJoinPillColor`
 * `--ag-advanced-filter-option-pill-color` -> `advancedFilterBuilderOptionPillColor`
 * `--ag-advanced-filter-value-pill-color` -> `advancedFilterBuilderValuePillColor`
 * `--ag-borders-input` -> `inputBorder`
 * `--ag-borders-input-invalid` -> `inputInvalidBorder`
 * `--ag-card-radius` -> `borderRadius`
 * `--ag-cell-horizontal-border` -> `columnBorder`
 * `--ag-chip-background-color` -> `columnDropCellBackgroundColor`
 * `--ag-chip-border-color` -> `columnDropCellBorder`
 * `--ag-control-panel-background-color` -> `chromeBackgroundColor`
 * `--ag-data-color` -> `cellTextColor`
 * `--ag-header-column-resize-handle-display` -> removed, use a transparent `headerColumnResizeHandleColor` to hide the resize handle
 * `--ag-header-column-separator-color`, `--ag-header-column-separator-width`, `--ag-header-column-separator-display` -> `headerColumnBorder`
 * `--ag-header-column-separator-height` -> `headerColumnBorderHeight`
 * `--ag-header-foreground-color` -> `headerTextColor`
 * `--ag-input-border-color` -> `inputBorder`
 * `--ag-input-border-color-invalid` -> `inputInvalidBorder`
 * `--ag-input-disabled-border-color` -> `inputDisabledBorder`
 * `--ag-input-focus-border-color` -> `inputFocusBorder`
 * `--ag-input-focus-box-shadow` -> `inputFocusShadow`
 * `--ag-menu-border-color` -> `menuBorderColor`
 * `--ag-panel-border-color` -> `dialogBorder`
 * `--ag-quartz-icon-active-color` -> this was used to apply an outline to focussed icons, now all focussed elements throughout the grid use `focusShadow`
 * `--ag-quartz-icon-hover-color` -> `iconButtonHoverColor`

#### Components with significantly different theming parameters

 * The [Sidebar](./side-bar/). Sidebar styling has been overhauled. Custom CSS rules you have written are likely still valid, but custom property names have changed. See [Customising Tool Panels](./theming-tool-panels/). In particular, in legacy themes the sidebar tabs shared the same custom properties as horizontal tabs. Now they have their own set of parameters beginning "sideBar" or "sideButton".
 * `--ag-checkbox-*` -> there has been a significant overhaul of checkbox parameters giving greater control over the appearance of checkboxes. See the Theming API docs. In v32, checkboxes used icons. Now they use their own set of CSS custom properties.
 *  `--ag-toggle-button-border-width`, `--ag-toggle-button-off-border-color`, `--ag-toggle-button-on-border-color`, and `--ag-toggle-button-switch-border-color` have been removed. In most use cases they can be replaced with the new `toggleButtonSwitchInset` parameter. Other use cases can use CSS. See [Styling Toggle Buttons](./theming-widgets/#styling-toggle-buttons) for an example.

#### Properties removed with no replacement, use CSS rules to achieve the same effect

These properties were either outdated, confusing to use, or provided no benefit over using CSS rules.

 * `--ag-secondary-border-color` -> there is no longer a concept of "secondary" borders use `borderColor` or CSS rules to target specific borders
 * `--ag-borders-side-button`
 * `--ag-tab-min-width`
 * `--ag-menu-min-width`
 * `--ag-subheader-toolbar-background-color`
 * `--ag-subheader-background-color`
 * `--ag-side-button-selected-background-color`
 * `--ag-spectrum-alpha-background-checked`
 * `--ag-chart-menu-pill-select-button-color`
 * `--ag-disabled-foreground-color`
 * `--ag-filter-tool-panel-sub-level-row-height`
 * `--ag-minichart-selected-chart-color`
 * `--ag-minichart-selected-page-color`

### 4. [optional] Remove ag-theme-* classes and update CSS rules that target them

Legacy themes were applied by adding a class name e.g. `ag-theme-quartz` to the wrapper element of the grid. Any CSS custom rules had to include this class name in order to override the styles defined in the theme. This is no longer required.

It is not required to remove the theme classname from your grid container, but if you do, you should also remove the class name from any CSS rules that target it:

Before:

```html
<div id="myGrid" class="ag-theme-quartz"></div>
```
```css
.ag-theme-quartz {
    --ag-foreground-color: red;
}
.ag-theme-quartz .ag-header-cell {
    font-style: italic;
}
```

After:

```html
<div id="myGrid"></div>
```
```css
body {
    /* set vars on `body` to affect all grids on the page regardless of the theme they
       use. You can also use a different selector to affect only specific grids. */
    --ag-foreground-color: red;
}
.ag-header-cell {
    font-style: italic;
}
```

### 4. [Sass users only] Remove use of the Sass API

The Theming API achieves in JavaScript what the old Sass API did in Sass.


## Incremental migration

If your application is split between multiple pages, it can be migrated one page at a time.

If a single HTML document contains multiple grids, we recommend migrating all the grids at the same time if possible - this is the most straightforward way of avoiding conflicts between the v32 styles and the Theming API.

In order to migrate one grid on a page that contains multiple grids, you can use shadow DOM to isolate grids using v32 styles from grids using the Theming API. Be aware however that this is an advanced technique and requires you to understand how shadow DOM works, and how it interacts with your framework and your application structure. Shadow DOM has other effects than simply isolating styles, and using it it may require code changes in your application.

{% if isFramework("react") %}

At AG Grid we have had success using the `react-shadow` package to migrate our website.

```jsx
import root from 'react-shadow';

// import of legacy themes
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-quartz.css';

// Use a grid with legacy themes as part of the main page
<div className="ag-theme-quartz" style={{height: '100%'}}>
    <AgGridReact
        theme='legacy'
        ... grid options ...
    />
</div>

// wrap a grid using Theming API in a shadow root
<root.div style={{ height: '100%' }}>
    <AgGridReact
        theme={themeQuartz}
        ... grid options ...
    />
</root.div>
```
{% /if %}

{% if isFramework("javascript") %}
See the [Shadow DOM API](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) documentation for more information.
{% /if %}


{% if isFramework("vue") %}
See the [Shadow DOM API](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) documentation for more information.
{% /if %}

{% if isFramework("angular") %}
For Angular, consider using [ViewEncapsulation.ShadowDom](https://angular.dev/guide/components/styling#viewencapsulationshadowdom) to create a shadow root for your grids using Theming API, leaving the grids using legacy themes in the main document. You can also use the [Shadow DOM API](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM) directly.
{% /if %}

## Understanding the Theming API

If you are familiar with the method of theming applications used in v32 and earlier, the following technical context will help you understand what is changing and what remains the same.

The grid is styled using CSS. A running grid instance contains thousands of DOM elements, and each of them has class names like `ag-header` and `ag-row` that can be used in CSS rules that change the style of that element. The grid package from NPM contains CSS that set up a default grid style and expose CSS custom properties (variables) that allow configuration of colors, borders, padding, fonts etc. When you want to go beyond what is possible with the custom properties, you write your own CSS rules targeting the grid's class names.

None of this is changing - the grid is still styled with CSS and CSS custom properties, and you can still extend it with your own CSS rules. What the Theming API changes is the following:

1. Instead of importing CSS files yourself, the grid is now responsible for inserting the correct CSS into the document head, at the correct position and in the correct order. This eliminates a class of bugs around incorrectly loading CSS files. The Theming API is integrated with the grid's module system so you only load CSS for features you're using, leading to a significant reduction in your app's size.
2. There is a TypeScript API for setting CSS custom properties (`theme.withParams(...)`). This provides autocompletion and inline documentation making it easier to find the property you're looking for. You can still set custom properties in CSS if you prefer.
3. It is now possible to mix and match elements of different themes. Previously, if you wanted the text inputs from Material and the buttons from Quartz, you would have to write your own styles. Now you can compose your own themes using parts from different built in themes (`theme.withPart(...)`).
4. It is a significant rewrite of the CSS we provide to style the grid, containing many improvements and resolving long-standing issues. It contains all the learnings from 10 years of maintaining the old CSS themes. Some examples of changes we've made:
    * Compactness and spacing has been completely overhauled. In legacy themes the size of many elements was set as a multiple of `--ag-grid-size`, so lower values produced a more compact grid. However in practice after changing the value, many further tweaks were required to get things looking right. In the Theming API this is replaced by `--ag-spacing` which is designed to "just work" at any value.
    * Focus styles look and work better, with focus styles on elements like header cells looking more like the focus styles on form inputs.
    * CSS custom properties now inherit as expected - if you set `--ag-foreground-color` on the `body` element, it will be inherited by all grids on the page. In legacy themes, the custom property had to be set on the same element as the theme class.
    * [Selector specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) has been reduced across the board, making it easier to override in your own style sheets. For example, in legacy themes if you added the following code to your application's style sheet - `.ag-cell-inline-editing { box-shadow: none; }` - it would not have the intended effect of removing the shadow from cells being edited. This was because our CSS that added the shadow had a more specific selector. In the Theming API this code works as expected.
    * Custom properties have been added, removed and renamed to make a more consistent and logical set. See [the migration instructions](./theming-migration/#3-convert-any-css-custom-properties-you-are-using-to-the-new-names) above for a list.